<?php

class TemplateParser {

	var $template;
	var $template_dir;
	var $extension_tagged = array();
	var $error;

	function TemplateParser ($template_filename) {
		// 载入模板内容
		if ($hd = @fopen($template_filename, "r")) {
			if (filesize($template_filename)) {
				$this->template = fread($hd, filesize($template_filename));
			} else {
				$this->template = "编译模板时发生错误: 无法读取模板文件: '$template_filename'";
			} 
			fclose($hd);
			$this->template_dir = dirname($template_filename);
		} else {
			$this->error("找不到要编译的模板文件: '$template_filename'");
		} 
	} 
	function compile($compiled_template_filename = '', $isCompile = '') {
		if (empty($this->template)) {
			return;
		} 
		if (eregi("<!-- INCLUDE", $this->template)) {
			while ($this->count_subtemplates() > 0) {
				preg_match_all('/<!-- INCLUDE ([a-zA-Z0-9\/_\.-]+) -->/', $this->template, $tvar);
				foreach($tvar[1] as $subfile) {
					if (file_exists($this->template_dir . "/$subfile")) {
						$subst = implode('', file($this->template_dir . "/$subfile"));
					} else {
						$subst = '编译模板时发生错误: 找不到要包含的文件\'' . $subfile . '\'';
					} 
					$this->template = str_replace("<!-- INCLUDE $subfile -->", $subst, $this->template);
				} 
			} 
		} 

		$page = preg_replace("/<!-- ENDIF.+?-->/", "<?php\n}\n?>", $this->template);
		$page = preg_replace("/<!-- END[ a-zA-Z0-9_.]* -->/", "<?php\n}\n\$_obj=\$_stack[--\$_stack_cnt];}\n?>", $page);
		$page = str_replace("<!-- ELSE -->", "<?php\n} else {\n?>", $page);
		$page = preg_replace("/\{ads_(.+)\}/","<?php\necho getAds('\\1');\n?>\n",$page);
		
		$page = str_replace("{admin}", ADMIN, $page); //系统名称
		$page = str_replace("{SITENAME}", SITE_NAME, $page); //系统名称
		$page = str_replace("{HOST}", SITE_HOST, $page); //系统根URL
		$page = str_replace("{PUB}", PUB, $page); //网站公共目录

		if (preg_match_all('/<!-- BEGIN ([a-zA-Z0-9_.]+) -->/', $page, $var)) {
			foreach ($var[1] as $tag) { // 循环处理
				list($parent, $block) = $this->var_name($tag); // 生成PHP代码
				$code = "<?php\n"
				 . "if (!empty(\$$parent" . "['$block'])){\n"
				 . "if (!is_array(\$$parent" . "['$block']))\n"
				 . "\$$parent" . "['$block']=array(array('$block'=>\$$parent" . "['$block']));\n"
				 . "\$_tmp_arr_keys=array_keys(\$$parent" . "['$block']);\n"
				 . "if (\$_tmp_arr_keys[0]!='0')\n"
				 . "\$$parent" . "['$block']=array(0=>\$$parent" . "['$block']);\n"
				 . "\$_stack[\$_stack_cnt++]=\$_obj;\n"
				 . "foreach (\$$parent" . "['$block'] as \$rowcnt=>\$$block) {\n"
				 . "\$$block" . "['ROWCNT']=\$rowcnt;\n"
				 . "\$$block" . "['ALTROW']=\$rowcnt%2;\n"
				 . "\$$block" . "['ROWBIT']=\$rowcnt%2;\n"
				 . "\$_obj=&\$$block;\n?>";
				$page = str_replace("<!-- BEGIN $tag -->", $code, $page); // 把原始内容替换成对应的PHP代码
			} 
		} 
		if (preg_match_all('/<!-- (ELSE)?IF ([a-zA-Z0-9_.]+)[ ]*([!=<>]+)[ ]*(["]?[^"]*["]?) -->/', $page, $var)) {
			foreach ($var[2] as $cnt => $tag) {
				list($parent, $block) = $this->var_name($tag);
				$cmp = $var[3][$cnt];
				$val = $var[4][$cnt];
				$else = ($var[1][$cnt] == 'ELSE') ? '} else' : '';
				if ($cmp == '=') {
					$cmp = '==';
				} 

				if (preg_match('/"([^"]*)"/', $val, $matches)) {
					$code = "<?php\n$else" . "if (\$$parent" . "['$block'] $cmp \"" . $matches[1] . "\"){\n?>";
				} elseif (preg_match('/([^"]*)/', $val, $matches)) {
					list($parent_right, $block_right) = $this->var_name($matches[1]);
					$code = "<?php\n$else" . "if (\$$parent" . "['$block'] $cmp \$$parent_right" . "['$block_right']){\n?>";
				} 

				$page = str_replace($var[0][$cnt], $code, $page);
			} 
		} 

		if (preg_match_all('/<!-- (ELSE)?IF ([a-zA-Z0-9_.]+) -->/', $page, $var)) {
			foreach ($var[2] as $cnt => $tag) {
				$else = ($var[1][$cnt] == 'ELSE') ? '} else' : '';
				list($parent, $block) = $this->var_name($tag);
				$code = "<?php\n$else" . "if (!empty(\$$parent" . "['$block'])){\n?>";
				$page = str_replace($var[0][$cnt], $code, $page);
			} 
		} 

		if (preg_match_all('/{((?:(?:[\x81-\xfe].)|(?:[a-zA-Z0-9_. >]))+)}/', $page, $var)) {
			foreach ($var[1] as $fulltag) {
				// Determin Command (echo / $obj[n]=)
				list($cmd, $tag) = $this->cmd_name($fulltag);

				list($block, $skalar) = $this->var_name($tag);
				$code = "<?php\n$cmd \$$block" . "['$skalar'];\n?>\n";
				$page = str_replace('{' . $fulltag . '}', $code, $page);
			} 
		} 
		if (preg_match_all('/{((?:(?:[\x81-\xfe].)|(?:[a-zA-Z0-9_. >]))+)}/', $page, $var)); {
			foreach ($var[1] as $tag) {
				list($block, $skalar) = $this->var_name($tag);
				$code = "<?php\necho gettext('$skalar');\n?>\n";
				$page = str_replace('<"' . $tag . '">', $code, $page);
			} 
		} 
		/**
		 * 文件头注释
		 * 
		 * @access private 
		 * @return void 
		 */
		$HeaderNotes = '<?php' . "\r\n"
		 . '//Compiled by TIBlog Template Engine v2.0 , Created on : ' . date("Y-m-d H:i:s") . "\r\n"
		 . 'defined(\'IN_DTE\') or exit(\'Access Denied\');' . "\r\n"
		 . '?>' . "\r\n";
		$page = $HeaderNotes . $page;

		if (isset($header) && !empty($header)) {
			$page = "<?php\n$header\n?>$page";
		} 
		if (strlen($compiled_template_filename)) {
			if ($hd = fopen($compiled_template_filename, "w")) {
				fwrite($hd, $page);
				fclose($hd);
				return true;
			} else {
				$this->error("编译后的文件不能被写入.请检查权限、路径是否正确.");
				return false;
			} 
		} else {
			return $page;
		} 
	} 

	function mkUrl($url) {
		$url = str_replace(array('/', '&'), array(PATH_DEPR, '-'), $url);
		return $url;
	} 
	function var_name($tag) {
		$parent_level = 0;
		while (substr($tag, 0, 7) == 'parent.') {
			$tag = substr($tag, 7);
			$parent_level++;
		} 
		if (substr($tag, 0, 4) == 'TOP.') {
			$obj = '_stack[0]';
			$tag = substr($tag, 4);
		} elseif ($parent_level) {
			$obj = '_stack[$_stack_cnt-' . $parent_level . ']';
		} else {
			$obj = '_obj';
		} while (is_int(strpos($tag, '.'))) {
			list($parent, $tag) = explode('.', $tag, 2);
			if (is_numeric($parent)) {
				$obj .= "[" . $parent . "]";
			} else {
				$obj .= "['" . $parent . "']";
			} 
		} 
		$ret = array($obj, $tag);
		return $ret;
	} 
	function cmd_name($tag) {
		if (preg_match('/^(.+) > ([a-zA-Z0-9_.]+)$/', $tag, $tagvar)) {
			$tag = $tagvar[1];
			list($newblock, $newskalar) = $this->var_name($tagvar[2]);
			$cmd = "\$$newblock" . "['$newskalar']=";
		} else {
			$cmd = "echo";
		} 
		$ret = array($cmd, $tag);
		return $ret;
	} 

	function count_subtemplates() {
		preg_match_all('/<!-- INCLUDE ([a-zA-Z0-9\/_\.-]+) -->/', $this->template, $tvar);
		$count_subtemplates = count($tvar[1]);
		$ret = intval($count_subtemplates);
		return $ret;
	} 

	function error($msg) {
		de($msg);
		exit();
	} 
} 

?>
